﻿// (c) Copyright Fernando Cerqueira.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using AppRes = WindowsPhoneCommands.Resources;
using AppConst = WindowsPhoneCommands.Constants;

// ReSharper disable CheckNamespace
namespace WindowsPhoneCommands
// ReSharper restore CheckNamespace
{
    /// <summary>
    /// Interaction logic for EditorWMAppManifestControl.xaml
    /// </summary>
    // ReSharper disable RedundantExtendsListEntry
    public partial class EditorWmAppManifestControl : UserControl
    // ReSharper restore RedundantExtendsListEntry
    {
        private bool _loaded;
        private readonly ToolWindowPane _parentWindow;

        private WmAppManifest _initialManifest;
        private string _projectName;
        private string _pathFileManifest;

        #region constructor

        public WindowsPhoneCommandsPackage Package
        {
            get
            {
                return (WindowsPhoneCommandsPackage)_parentWindow.Package;
            }
        }

        public EditorWmAppManifestControl()
            : this(null)
        {

        }

        public EditorWmAppManifestControl(ToolWindowPane parentWindow)
        {
            _parentWindow = parentWindow;

            InitializeComponent();

            Loaded += MainControlLoaded;

        }

        private void MainControlLoaded(object sender, RoutedEventArgs e)
        {
            if (!_loaded)
            {
                var toolwin = (WmAppManifestToolWindow)_parentWindow;
                _projectName = toolwin.OwnerProject;
                _pathFileManifest = toolwin.WmAppManifestFilePath;

                var fileName = new System.IO.FileInfo(_pathFileManifest).Name;
                LblProjectAssembly.Text = toolwin.AssemblyProject;

                _parentWindow.Caption = fileName + " (" + _projectName + ")";

                Background = VsTheming.GetDialogBackground();
                Foreground = VsTheming.GetWindowText();

                var seletedProject = EnvPhoneDevice.FindProjectByName(Package.EnvDte, _projectName);

                var imagesSeletedProject = EnvPhoneDevice.GetListFilesFromProject(seletedProject,
                                                       new[] { ".PNG", ".JPG", ".JPEG", ".BMP" });

                var fileXamlseletedProject = EnvPhoneDevice.GetListFilesFromProject(seletedProject,
                                                                       new[] { ".XAML" });

                CboIcon.ItemsSource = imagesSeletedProject;
                CboTileBg.ItemsSource = imagesSeletedProject;
                CboStartPage.ItemsSource = fileXamlseletedProject;

                LoadXml();

            }
            _loaded = true;
        }

        private void NumericTextInput(object sender, TextCompositionEventArgs e)
        {
            e.Handled = !Common.ValidNumericChars(e.Text);
            base.OnPreviewTextInput(e);
        }


        #endregion

        private void LoadXml()
        {
            _initialManifest = EnvPhoneDevice.ReadWmAppManifest(Package.EnvDte, _projectName);
            TxtAuthor.Text = _initialManifest.Author;
            TxtDesc.Text = _initialManifest.Description;
            TxtPublisher.Text = _initialManifest.Publisher;
            TxtTile.Text = _initialManifest.TileTitle;
            TxtTileCount.Text = _initialManifest.TileCount;
            TxtTitle.Text = _initialManifest.Title;
            TxtToken.Text = _initialManifest.TokenId;
            var version = _initialManifest.Version.Split('.');
            TxtVerMax.Text = version[0];
            if (version.Length > 1)
            {
                TxtVerMin.Text = version[1];
            }
            if (version.Length > 2)
            {
                TxtVerRev.Text = version[2];
            }
            if (version.Length > 3)
            {
                TxtVerBld.Text = version[3];
            }
            ChkApp.IsChecked = _initialManifest.CapAppointments;
            ChkBeta.IsChecked = _initialManifest.IsBeta;
            ChkCam.IsChecked = _initialManifest.CapCamera;
            ChkCont.IsChecked = _initialManifest.CapContacts;
            ChkDiler.IsChecked = _initialManifest.CapPhoneDialer;
            ChkGame.IsChecked = _initialManifest.CapGamerSrv;
            ChkIdDev.IsChecked = _initialManifest.CapIdentDevive;
            ChkIdUser.IsChecked = _initialManifest.CapIdentUser;
            ChkLoc.IsChecked = _initialManifest.CapLocation;
            ChkMedLib.IsChecked = _initialManifest.CapMediaLib;
            ChkMic.IsChecked = _initialManifest.CapMicrophone;
            ChkPush.IsChecked = _initialManifest.CapPushNotif;
            ChkSen.IsChecked = _initialManifest.CapSensor;
            ChkSett.IsChecked = _initialManifest.HasSettings;
            ChkSingle.IsChecked = _initialManifest.SingleInst;
            ChkWeb.IsChecked = _initialManifest.CapWebBrowser;
            ChklNet.IsChecked = _initialManifest.CapNetworking;

            CboIcon.Text = _initialManifest.IconApp;
            CboStartPage.Text = _initialManifest.StartPage;
            CboTileBg.Text = _initialManifest.TileBackground;

            ValidateValues(false);

        }

        private void SupressSpaceLostFocus(object sender, RoutedEventArgs e)
        {
            var textbox = (TextBox) sender;
            textbox.Text = textbox.Text.Trim();
            ValidateValues(false);
        }

        private void CheckCbo(object sender, RoutedEventArgs e)
        {
            ValidateValues(false);
        }

        private void LnkCopyAssemblyMouseEnter(object sender, MouseEventArgs e)
        {
            LblCopyAssembly.Foreground = VsTheming.GetWindowHighlightText();
            LblProjectAssembly.Foreground = VsTheming.GetWindowHighlightText();
        }

        private void LnkCopyAssemblyMouseLeave(object sender, MouseEventArgs e)
        {
            LblCopyAssembly.Foreground = VsTheming.GetWindowText();
            LblProjectAssembly.Foreground = VsTheming.GetWindowText();
        }

        private void LnkCopyAssemblyMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var version = LblProjectAssembly.Text.Split('.');
            TxtVerMax.Text = version[0];
            if (version.Length > 1)
            {
                TxtVerMin.Text = version[1];
            }
            if (version.Length > 2)
            {
                TxtVerRev.Text = version[2];
            }
            if (version.Length > 3)
            {
                TxtVerBld.Text = version[3];
            }
            ValidateValues(false);
        }

        private static int Adorne(Control control,bool error,string tootip)
        {
            if (error)
            {
                var colorerr = VsTheming.GetColorError();
                if (control.BorderBrush != colorerr)
                {
                    control.Tag = control.BorderBrush;
                    control.BorderBrush = colorerr;
                    control.ToolTip = tootip;
                }
            }
            else
            {
                if (control.BorderBrush != control.Tag && control.Tag != null)
                {
                    control.BorderBrush = (Brush)control.Tag;
                }
            }
            return error ? 1 : 0;
        }

        private bool ValidateValues(bool showmsg)
        {
            var qtderr = 0;
            qtderr += Adorne(TxtAuthor, TxtAuthor.Text.Length == 0,AppRes.RequiredField);
            qtderr += Adorne(TxtDesc, TxtDesc.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtPublisher, TxtPublisher.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtTile, false, AppRes.RequiredField);
            qtderr += Adorne(TxtTileCount, TxtTileCount.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtTitle, TxtTitle.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtToken, TxtToken.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtVerMax, TxtVerMax.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtVerMin, TxtVerMin.Text.Length == 0, AppRes.RequiredField);
            qtderr += Adorne(TxtVerRev, false, AppRes.RequiredField);
            qtderr += Adorne(TxtVerBld, false, AppRes.RequiredField);
            if (TxtVerBld.Text.Length > 0)
            {
                if (TxtVerRev.Text.Length == 0)
                {
                    qtderr += Adorne(TxtVerRev, true, AppRes.RequiredField);
                }
            }
            qtderr += Adorne(CboIcon, !CboIcon.Items.Contains(CboIcon.Text), AppRes.RequiredField);
            qtderr += Adorne(CboStartPage, !CboStartPage.Items.Contains(CboStartPage.Text), AppRes.RequiredField);
            qtderr += Adorne(CboTileBg, !CboTileBg.Items.Contains(CboTileBg.Text), AppRes.RequiredField);
            if (qtderr > 0 && showmsg)
            {
                MessageBox.Show(AppRes.ErrCompleteFields, AppRes.ToolWindowTitle, MessageBoxButton.OK, MessageBoxImage.Error);
            }
            return (qtderr == 0);
        }

        private void BackgroundSaveManifest(Cursor oldcur)
        {
            try
            {
                // ReSharper disable PossibleNullReferenceException
                var xmldoc = new XmlDocument();
                xmldoc.Load(_pathFileManifest);
                var selectedNode = xmldoc.GetElementsByTagName("App")[0];
                selectedNode.Attributes["Title"].Value = Common.XmlEscape(TxtTitle.Text.Trim());
                var ver = TxtVerMax.Text.Trim() + "." + TxtVerMin.Text.Trim();
                if (TxtVerRev.Text.Trim().Length > 0)
                {
                    ver += "." + TxtVerRev.Text.Trim();
                    if (TxtVerBld.Text.Trim().Length > 0)
                    {
                        ver += "." + TxtVerBld.Text.Trim();
                    }
                }
                selectedNode.Attributes["Version"].Value = ver;
                selectedNode.Attributes["Author"].Value = Common.XmlEscape(TxtAuthor.Text.Trim());
                selectedNode.Attributes["Description"].Value = Common.XmlEscape(TxtDesc.Text.Trim());
                selectedNode.Attributes["Publisher"].Value = Common.XmlEscape(TxtPublisher.Text.Trim());
                if (ChkBeta.IsChecked != null && ChkBeta.IsChecked.Value)
                {
                    if (selectedNode.Attributes["IsBeta"] == null)
                    {
                        var newatt = xmldoc.CreateAttribute("IsBeta");
                        newatt.Value = bool.TrueString.ToLower();
                        selectedNode.Attributes.Append(newatt);
                    }
                    else
                    {
                        selectedNode.Attributes["IsBeta"].Value = bool.TrueString.ToLower();
                    }
                }
                else
                {
                    if (selectedNode.Attributes["IsBeta"] != null)
                    {
                        selectedNode.Attributes.Remove(selectedNode.Attributes["IsBeta"]);
                    }
                }
                if (ChkSett.IsChecked != null && ChkSett.IsChecked.Value)
                {
                    if (selectedNode.Attributes["HasSettings"] == null)
                    {
                        var newatt = xmldoc.CreateAttribute("HasSettings");
                        newatt.Value = bool.TrueString.ToLower();
                        selectedNode.Attributes.Append(newatt);
                    }
                    else
                    {
                        selectedNode.Attributes["HasSettings"].Value = bool.TrueString.ToLower();
                    }
                }
                else
                {
                    if (selectedNode.Attributes["HasSettings"] != null)
                    {
                        selectedNode.Attributes.Remove(selectedNode.Attributes["HasSettings"]);
                    }
                }
                if (ChkSingle.IsChecked != null && ChkSingle.IsChecked.Value)
                {
                    if (selectedNode.Attributes["SingleInstanceHost"] == null)
                    {
                        var newatt = xmldoc.CreateAttribute("SingleInstanceHost");
                        newatt.Value = bool.TrueString.ToLower();
                        selectedNode.Attributes.Append(newatt);
                    }
                    else
                    {
                        selectedNode.Attributes["SingleInstanceHost"].Value = bool.TrueString.ToLower();
                    }
                }
                else
                {
                    if (selectedNode.Attributes["SingleInstanceHost"] != null)
                    {
                        selectedNode.Attributes.Remove(selectedNode.Attributes["SingleInstanceHost"]);
                    }
                }

                selectedNode = xmldoc.GetElementsByTagName("IconPath")[0];
                selectedNode.InnerText = Common.XmlEscape(CboIcon.Text);

                selectedNode = xmldoc.GetElementsByTagName("Capabilities")[0];
                selectedNode.RemoveAll();
                if (ChkGame.IsChecked != null && ChkGame.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapGamerservices;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkIdDev.IsChecked != null && ChkIdDev.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapIdentityDevice;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkIdUser.IsChecked != null && ChkIdUser.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapIdentityUser;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkLoc.IsChecked != null && ChkLoc.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapLocation;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkMedLib.IsChecked != null && ChkMedLib.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapMedialib;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkMic.IsChecked != null && ChkMic.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapMicrophone;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChklNet.IsChecked != null && ChklNet.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapNetworking;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkDiler.IsChecked != null && ChkDiler.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapPhonedialer;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkPush.IsChecked != null && ChkPush.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapPushNotification;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkSen.IsChecked != null && ChkSen.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapSensors;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkWeb.IsChecked != null && ChkWeb.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapWebbrowsercomponent;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkCam.IsChecked != null && ChkCam.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapIsvCamera;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkCont.IsChecked != null && ChkCont.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapContacts;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }
                if (ChkApp.IsChecked != null && ChkApp.IsChecked.Value)
                {
                    var newcap = xmldoc.CreateNode(XmlNodeType.Element, "Capability", string.Empty);
                    var newatt = xmldoc.CreateAttribute("Name");
                    newatt.Value = AppConst.IdCapAppointments;
                    newcap.Attributes.Append(newatt);
                    selectedNode.AppendChild(newcap);
                }

                selectedNode = xmldoc.GetElementsByTagName("DefaultTask")[0];
                selectedNode.Attributes["NavigationPage"].Value = Common.XmlEscape(CboStartPage.Text);

                selectedNode = xmldoc.GetElementsByTagName("PrimaryToken")[0];
                selectedNode.Attributes["TokenID"].Value = Common.XmlEscape(TxtToken.Text.Trim());

                selectedNode = xmldoc.GetElementsByTagName("TemplateType5")[0];
                foreach (XmlNode item in selectedNode.ChildNodes)
                {
                    if (item.NodeType == XmlNodeType.Element && item.Name == "BackgroundImageURI")
                    {
                        item.InnerText = Common.XmlEscape(CboTileBg.Text);
                    }
                    else if (item.NodeType == XmlNodeType.Element && item.Name == "Count")
                    {
                        item.InnerText = TxtTileCount.Text.Trim();
                    }
                    else if (item.NodeType == XmlNodeType.Element && item.Name == "Title")
                    {
                        item.InnerText = Common.XmlEscape(TxtTile.Text.Trim());
                    }
                }
                // ReSharper restore PossibleNullReferenceException


                var docs = Package.EnvDte.Documents;
                var enumdocs = docs.GetEnumerator();
                Document docEdit = null;
                while (enumdocs.MoveNext())
                {
                    var doc = (Document)enumdocs.Current;
                    if (doc.FullName == _pathFileManifest)
                    {
                        docEdit = doc;
                        docEdit.Activate();
                        break;
                    }
                }
                if (docEdit == null)
                {
                    var subitems = EnvPhoneDevice.FindProjectByName(Package.EnvDte,_projectName).ProjectItems.GetEnumerator();
                    while (subitems.MoveNext())
                    {
                        var tmp = EnvPhoneDevice.GetManifestWp((ProjectItem)subitems.Current);
                        if (tmp != null)
                        {
                            tmp.Open();
                            docEdit = tmp.Document;
                            docEdit.Activate();
                            break;
                        }
                    }
                }
                if (docEdit == null)
                {
                    var atucur = Cursor;
                    Cursor = oldcur;
                    MessageBox.Show(AppRes.ManifNotFound, AppRes.ToolWindowTitle, MessageBoxButton.OK, MessageBoxImage.Error);
                    Cursor = atucur;
                }
                else
                {
                    var settings = new XmlWriterSettings
                    {
                        Indent = true,
                        IndentChars = "\t",
                        OmitXmlDeclaration = true,
                        NewLineOnAttributes = false
                    };

                    var output = new StringBuilder();
                    var writer = XmlWriter.Create(output, settings);
                    xmldoc.WriteContentTo(writer);
                    writer.Flush();

                    var textselect = (TextSelection)docEdit.Selection;
                    textselect.SelectAll();
                    textselect.Insert(output.ToString());
                    textselect.GotoLine(1);
                    writer.Close();
                    docEdit.Save();
                    Cursor = oldcur;
                    IsEnabled = true;
                    Package.CloseWindow(_parentWindow);
                    return;
                }
            }
            catch (Exception ex)
            {
                Cursor = oldcur;
                MessageBox.Show(AppRes.ErrSavingFileManif + ex, AppRes.ToolWindowTitle, MessageBoxButton.OK, MessageBoxImage.Error);
            }
            Cursor = oldcur;
            IsEnabled = true;

        }

        private void BntSaveClick(object sender, RoutedEventArgs e)
        {
            if (ValidateValues(true))
            {
                var oldcur = Cursor;
                Cursor = Cursors.Wait;
                IsEnabled = false;
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action<Cursor>(BackgroundSaveManifest),oldcur);
            }
        }

        private void BntShowXmlClick(object sender, RoutedEventArgs e)
        {
            try
            {
                var docs = Package.EnvDte.Documents;
                var enumdocs = docs.GetEnumerator();
                Document docEdit = null;
                while (enumdocs.MoveNext())
                {
                    var doc = (Document)enumdocs.Current;
                    if (doc.FullName == _pathFileManifest)
                    {
                        docEdit = doc;
                        docEdit.Activate();
                        Package.CloseWindow(_parentWindow);
                        break;
                    }
                }
                if (docEdit == null)
                {
                    var subitems = EnvPhoneDevice.FindProjectByName(Package.EnvDte, _projectName).ProjectItems.GetEnumerator();
                    while (subitems.MoveNext())
                    {
                        var tmp = EnvPhoneDevice.GetManifestWp((ProjectItem)subitems.Current);
                        if (tmp != null)
                        {
                            tmp.Open();
                            docEdit = tmp.Document;
                            docEdit.Activate();
                            Package.CloseWindow(_parentWindow);
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, AppRes.ToolWindowTitle, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

    }
}
